package com.echo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.echo.dao.UserDAO;
import com.echo.entity.dto.UserDestroyAccountDTO;
import com.echo.entity.dto.UserLoginDTO;
import com.echo.entity.dto.UserRegisterDTO;
import com.echo.entity.dto.UserUpdateDTO;
import com.echo.entity.pojo.User;
import com.echo.entity.vo.UserDetailedInfoVO;
import com.echo.entity.vo.UserMainPageVO;
import com.echo.utils.DateTimeTransferUtil;
import com.echo.utils.JwtUtil;
import com.echo.utils.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackForClassName = "Exception.class")
public class UserServiceImpl extends ServiceImpl<UserDAO, User> {
    private UserDAO userDAO;
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    private JwtUtil jwtUtil;
    private RedisUtil redisUtil;

    public UserServiceImpl(UserDAO userDAO, BCryptPasswordEncoder bCryptPasswordEncoder, JwtUtil jwtUtil, RedisUtil redisUtil) {
        this.userDAO = userDAO;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.jwtUtil = jwtUtil;
        this.redisUtil = redisUtil;
    }

    public UserMainPageVO getUserMainPageInfo(int userId) {
        UserMainPageVO userMainPageInfo = userDAO.getUserMainPageInfo(userId);
        return userMainPageInfo;
    }

    public UserDetailedInfoVO getUserDetailedInfo(int userId) {
        UserDetailedInfoVO userDetailedInfo = userDAO.getUserDetailedInfo(userId);
        return userDetailedInfo;
    }

    /**
     * 新用户注册
     *
     */
    public void userRegister(UserRegisterDTO userRegisterDTO){

        //检验是否重名
        User userQueryByName = userDAO.selectOne(new QueryWrapper<User>().eq("username",userRegisterDTO.getUsername()));
        if (userQueryByName!=null){
            throw new DuplicateKeyException("用户名重复");
        }
        try {
            User newUser = new User();
            BeanUtils.copyProperties(userRegisterDTO,newUser);
            newUser.setPassword(bCryptPasswordEncoder.encode(userRegisterDTO.getPassword()));
            newUser.setBanStatus(0);
            newUser.setIdentityStatus(0);
            newUser.setCreateTime(Long.getLong(DateTimeTransferUtil.getNowTimeStamp()));
            newUser.setUpdateTime(newUser.getCreateTime());
            userDAO.insert(newUser);
        }catch (Exception e){
            throw e;
        }
    }

    /**
     * 用户登录
     * @param userLoginDTO
     */
    public String userLogin(UserLoginDTO userLoginDTO){
        User user = userDAO.selectOne(new QueryWrapper<User>().eq("username", userLoginDTO.getUsername()));
        if (user==null){
            throw new InternalAuthenticationServiceException("用户名错误或不存在");
        }

        //检验用户封禁状态
        if(user.getBanStatus()!=0){
            throw new BadCredentialsException("账号状态异常");
        }
        //检验密码，如密码正确，生成jwt并返回
        if (!bCryptPasswordEncoder.matches(userLoginDTO.getPassword(),user.getPassword())){
            //登录失败
            throw new InternalAuthenticationServiceException("密码错误");
        }
        System.out.println(user);
        //将新用户的身份状态存入redis
        redisUtil.set("IS_"+user.getId()+"",user.getIdentityStatus(),259000000);
        return jwtUtil.createJWT(user.getId()+"",user.getUsername(),user.getAvatar());
    }

    /**
     * 用户更新个人信息
     */
    public void updatePersonalInfo(UserUpdateDTO userUpdateDTO,Integer uid){
        //检验用户名是否重复
        if(userDAO.selectOne(new QueryWrapper<User>().eq("username",userUpdateDTO.getUsername()))!=null){
            throw new DuplicateKeyException("用户名重复");
        }
        //更新信息
        User user = userDAO.selectById(uid);
        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.eq("id",user.getId()).set("username",userUpdateDTO.getUsername())
                .set("password",bCryptPasswordEncoder.encode(userUpdateDTO.getPassword()));
        userDAO.update(null, userUpdateWrapper);
    }

    /**
     * 用户注销个人账户
     */
    public void destroyAccount(UserDestroyAccountDTO userDestroyAccountDTO,Integer uid){
        User user = userDAO.selectOne(new QueryWrapper<User>().eq("username", userDestroyAccountDTO.getUsername())
        .eq("id",uid));

        if (user==null){
            throw new InternalAuthenticationServiceException("注销失败");
        }

        //检验密码
        if (!bCryptPasswordEncoder.matches(userDestroyAccountDTO.getPassword(),user.getPassword())){
            //销毁失败
            throw new InternalAuthenticationServiceException("密码错误");
        }
    }
}


